package com.platform.core.web.controller;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Maps;
import com.platform.aspect.WebLog;
import com.platform.comm.enums.YnEnum;
import com.platform.comm.jwt.JwtTokenUtil;
import com.platform.comm.jwt.TokenInfoUtil;
import com.platform.comm.util.WebIOUtil;
import com.platform.comm.validation.groups.Insert;
import com.platform.comm.validation.groups.Modify;
import com.platform.comm.validation.groups.Pwd;
import com.platform.core.security.auth.AuthenticationFacade;
import com.platform.core.service.SysUserRoleService;
import com.platform.core.service.SysUserService;
import com.platform.dto.DepartQo;
import com.platform.dto.PwdQo;
import com.platform.dto.UserInfoQo;
import com.platform.dto.UserQo;
import com.platform.enums.CommFlagType;
import com.querydsl.core.BooleanBuilder;
import com.platform.comm.web.results.DataJsonResult;
import com.platform.comm.web.results.JsonResult;
import com.platform.comm.web.results.PageListDto;
import com.platform.comm.web.results.PageListJsonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Description: 用户管理
 *
 * @author libin
 * Created on 2019/4/19
 **/
@RestController
@RequestMapping("/management/user")
@Slf4j
public class SysUserController extends BaseController {

    private final SysUserService sysUserService;
    private final SysUserRoleService sysUserRoleService;
    private final TokenInfoUtil tokenInfoUtil;

    public SysUserController(SysUserService sysUserService, SysUserRoleService sysUserRoleService,
                             TokenInfoUtil tokenInfoUtil) {
        this.sysUserService = sysUserService;
        this.sysUserRoleService = sysUserRoleService;
        this.tokenInfoUtil = tokenInfoUtil;
    }

    @WebLog(theme = "新增[用户]", moduleName = "用户管理", type = WebLog.OpType.ADD, root = UserQo.class)
    @PostMapping(name = "新增用户", path = "create")
    public JsonResult create(@Validated({Insert.class}) @RequestBody UserQo userQo) {
        return createOrModifyWithResult(sysUserService::create, userQo);
    }

    @WebLog(theme = "修改[用户]", moduleName = "用户管理", type = WebLog.OpType.MOD, root = UserQo.class)
    @PostMapping(name = "修改用户", path = "modify")
    public JsonResult modify(@Validated({Modify.class}) @RequestBody UserQo userQo) {
        return createOrModifyWithResult(sysUserService::modify, userQo);
    }

    @WebLog(theme = "删除用户", moduleName = "用户管理", type = WebLog.OpType.DEL,
            root = Map.class, params = {"paramsMap"})
    @PostMapping(name = "删除用户", path = "remove")
    public JsonResult remove(@RequestBody Map<String, String> paramsMap) {
        return removeOrOtherByIds(sysUserService::remove, paramsMap.get("id"));
    }

    @WebLog(theme = "批量删除用户", moduleName = "用户管理", type = WebLog.OpType.DEL_BATCH,
            root = List.class)
    @PostMapping(name = "删除用户", path = "batchRemove")
    public JsonResult batchRemove(@RequestBody List<String> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            return modify(sysUserService::changeDelFlag, ids.get(0), YnEnum.Y);
        }
        return modify(sysUserService::changeDelFlag, ids, YnEnum.Y);
    }

    @WebLog(theme = "修改[用户状态]", moduleName = "用户管理", type = WebLog.OpType.MOD, root = Map.class)
    @PostMapping(name = "修改用户状态", path = "/changeStatus")
    public JsonResult changeUserStatus(@RequestBody Map<String, Object> paramsMap) {
        String flagType = paramsMap.get("flagType").toString();
        List<String> ids = (List<String>) paramsMap.get("ids");
        if (CollUtil.isNotEmpty(ids)) {
            return modify(sysUserService::changeStatus, ids.get(0), CommFlagType.getFlagByValue(flagType));
        }
        return modify(sysUserService::changeStatus, ids, CommFlagType.getFlagByValue(flagType));
    }

    @PostMapping(name = "分页查询用户", path = "search")
    public PageListJsonResult<UserQo> search(@RequestBody(required = false) Map<String, String> paramsMap) {
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        if (CollUtil.isNotEmpty(paramsMap)) {
            paramsMap.forEach(parameters::add);
        }
        return new PageListJsonResult<>(sysUserService.queryUsers(new BooleanBuilder(), getPageable(paramsMap), parameters, sysUserRoleService.checkAccessSubOrg()));
    }

    @PostMapping(name = "流程引擎-查询用户", path = "searchForFlow")
    public DataJsonResult<List<Map<String, String>>> searchForFlow(@RequestBody Map<String, String> paramsMap) {
        PageListJsonResult<UserQo> search = this.search(paramsMap);
        List<Map<String, String>> rows = search.getRows().stream().map(item -> {
            Map<String, String> data = Maps.newHashMap();
            data.put("id", item.getId());
            data.put("name", item.getRealName());
            data.put("departName", item.getDepartName());
            return data;
        }).collect(Collectors.toList());
        return DataJsonResult.succeed(rows);
    }

    @PostMapping(name = "分页查询负责人列表", path = "searchLeader")
    public PageListJsonResult<UserQo> searchLeader(@RequestBody(required = false) Map<String, String> paramsMap) {
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        if (CollUtil.isNotEmpty(paramsMap)) {
            paramsMap.forEach(parameters::add);
        }
        return new PageListJsonResult<>(sysUserService.searchLeader(getPageable(paramsMap), parameters));
    }

    @PostMapping(name = "检查用户名是否存在", path = "checkUsernameExists")
    public DataJsonResult<Long> checkUsernameExists(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        String username = paramsMap.get("username");
        return query(sysUserService::checkUsernameExists, id, username);
    }

    @PostMapping(name = "检查邮箱是否存在", path = "checkEmailExists")
    public DataJsonResult<Long> checkEmailExists(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        String email = paramsMap.get("email");
        return query(sysUserService::checkEmailExists, id, email);
    }

    @PostMapping(name = "检查手机号否存在", path = "checkMobileExists")
    public DataJsonResult<Long> checkMobileExists(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        String mobile = paramsMap.get("mobile");
        return query(sysUserService::checkMobileExists, id, mobile);
    }

    @PostMapping(name = "检查身份证号否存在", path = "checkIdCodeExists")
    public DataJsonResult<Long> checkIdCodeExists(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        String idCode = paramsMap.get("idCode");
        return query(sysUserService::checkIdCodeExists, id, idCode);
    }

    @PostMapping(name = "检查用户编码是否存在", path = "checkUserCodeExists")
    public DataJsonResult<Long> checkUserCodeExists(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        String userCode = paramsMap.get("userCode");
        return query(sysUserService::checkUserCodeExists, id, userCode);
    }

    @WebLog(theme = "用户密码重置", moduleName = "用户管理", type = WebLog.OpType.DEL,
            root = Map.class, params = {"paramsMap"})
    @PostMapping(name = "用户密码重置", path = "/resetPwd")
    public JsonResult resetPwd(@RequestBody Map<String, Object> paramsMap) {
        List<String> ids = (List<String>) paramsMap.get("ids");
        return removeOrOtherByIds(sysUserService::resetPwd, ids);
    }

    @WebLog(theme = "修改[用户密码]", moduleName = "用户管理", type = WebLog.OpType.MOD, root = PwdQo.class)
    @PostMapping(name = "修改用户密码", path = "modifyPwd")
    public JsonResult modifyPwd(@Validated(Pwd.class) @RequestBody PwdQo pwd) {
        return modify(sysUserService::modifyPwd, AuthenticationFacade.getUserName(), pwd);
    }

    @PostMapping(name = "同步用户到子系统", path = "syncSubsystem")
    public JsonResult syncSubsystem(@RequestBody Map<String, String> paramsMap) {
        String id = paramsMap.get("id");
        return removeOrOtherByIds(sysUserService::syncSubsystem, id);
    }

    @PostMapping(name = "下载用户模板", path = "/downloadUserTemplate")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        ClassPathResource resource = new ClassPathResource("templates/用户模板.xlsx");
        InputStream tempFile = resource.getInputStream();
        File targetFile = File.createTempFile("用户模板", ".xlsx");
        FileUtils.copyInputStreamToFile(tempFile, targetFile);
        Path path = Paths.get(targetFile.getPath());
        try {
            WebIOUtil.download(path, response, FilenameUtils.getName(path.toString()));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("下载模板文件失败", e);
        }
    }

    /**
     * 根据token 获取采集用户信息
     *
     * @param user 用户
     * @return 用户信息
     */
    @PostMapping("/gatherUserInfo")
    public UserInfoQo gatherUserInfo(@RequestBody JwtTokenUtil.JwtUser user) {
        return sysUserService.gatherUserInfo(user);
    }

    /**
     * 根据token 获取采集用户信息
     *
     * @return 用户信息
     */
    @PostMapping("/gatherUserInfoNoParam")
    public UserInfoQo gatherUserInfoNoParam() {
        return sysUserService.gatherUserInfo(tokenInfoUtil.getUser());
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    @PostMapping("/getByUserId")
    public UserQo getByUserId(String userId) {
        return sysUserService.getByUserId(userId);
    }

    @PostMapping("/getByUserAll")
    public List<UserQo> getByUserAll() {
        return sysUserService.getByUserAll();
    }


    /**
     * 根据用户ID数组查询用户信息列表
     *
     * @param userIds 用户ID
     * @return 用户信息
     */
    @PostMapping("/getByUserIds")
    public List<UserQo> getByUserIds(@RequestBody List<String> userIds) {
        return sysUserService.getByUserId(userIds);
    }

    /**
     * 根据部门id获取用户列表
     *
     * @param paramsMap 部门id
     * @return 用户ids
     */
    @PostMapping("/getByDepart")
    public PageListDto<String> getByDepartId(@RequestBody Map<String, String> paramsMap) {
        return PageListDto.of(sysUserService.getByDepartId(paramsMap.get("departId"), getPageable(paramsMap)));
    }


    /**
     * 获取用户岗位信息
     *
     * @return 用户信息
     */
    @PostMapping("/getPostUserInfo")
    public List<DepartQo> getPostUserInfo() {
        return sysUserService.getPostUserInfo();
    }

    /**
     * 设置岗位信息
     */
    @PostMapping("/setPost")
    public JsonResult setPost(@RequestBody Map<String, Object> params) {
        sysUserService.setPost(params);
        return JsonResult.success();
    }

    @WebLog(theme = "新增非系统用户", moduleName = "用户管理", type = WebLog.OpType.ADD, root = UserQo.class)
    @PostMapping(name = "新增非系统用户", path = "createOtherUser")
    public JsonResult createOtherUser(@Validated({Insert.class}) @RequestBody UserQo userQo) {
        return createOrModifyWithResult(sysUserService::createOtherUser, userQo);
    }

    @WebLog(theme = "根据名称查询用户", moduleName = "用户管理", type = WebLog.OpType.SEARCH, root = UserQo.class)
    @PostMapping(name = "根据名称查询用户", path = "getUserByUserName")
    public UserQo getUserByUserName(@RequestBody UserQo userQo) {
        return this.sysUserService.getUserByUserName(userQo);
    }

}
